gloomberb 0.18.1 → 0.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/patches/electrobun@1.18.1.patch +106 -5
- package/src/api-client/commodity-balances.ts +6 -0
- package/src/api-client/company-kpis.ts +9 -0
- package/src/api-client/crypto-markets.ts +9 -0
- package/src/api-client/data.ts +21 -5
- package/src/api-client/equity-screener.ts +2 -0
- package/src/api-client/index.ts +2 -0
- package/src/api-client/request.ts +5 -3
- package/src/api-client/telemetry.ts +17 -0
- package/src/api-client/types.ts +5 -0
- package/src/app/global-shortcuts.ts +1 -16
- package/src/app/pane-runtime/plugin-bindings.ts +3 -1
- package/src/app/pane-runtime/ticker-open-runtime.ts +17 -5
- package/src/app/runtime/plugin-bindings.ts +6 -2
- package/src/app/runtime/update.ts +28 -8
- package/src/architecture/pane-tabs-allowlist.json +65 -0
- package/src/brokers/logos.ts +66 -0
- package/src/brokers/profile-form.ts +3 -0
- package/src/brokers/remote-broker-adapter.ts +13 -3
- package/src/capabilities/index.ts +1 -1
- package/src/capabilities/service-capabilities.ts +7 -1
- package/src/cli/base-converter.ts +60 -18
- package/src/cli/commands/market.ts +354 -187
- package/src/cli/commands/news-search.ts +35 -8
- package/src/cli/commands/system.ts +35 -1
- package/src/cli/commands/ticker.ts +167 -60
- package/src/cli/currency-hints.ts +27 -0
- package/src/cli/fx-pair.ts +41 -4
- package/src/cli/glossary.ts +57 -4
- package/src/cli/help.ts +1 -1
- package/src/cli/helpers.ts +36 -3
- package/src/cli/index.ts +12 -1
- package/src/cli/issuer-membership.ts +103 -0
- package/src/cli/known-gaps.ts +37 -1
- package/src/cli/listing-arg.ts +51 -3
- package/src/cli/name-entries.ts +51 -12
- package/src/cli/pane-functions/capabilities.ts +2 -0
- package/src/cli/pane-functions/catalog.ts +19 -1
- package/src/cli/pane-functions/discovery.ts +15 -1
- package/src/cli/pane-functions/dom.ts +11 -5
- package/src/cli/pane-functions/freshness.ts +4 -4
- package/src/cli/pane-functions/function-help.ts +27 -3
- package/src/cli/pane-functions/headless.ts +31 -11
- package/src/cli/pane-functions/index.ts +67 -7
- package/src/cli/pane-functions/lock-note.ts +7 -4
- package/src/cli/pane-functions/resolver.ts +21 -6
- package/src/cli/quote-answer.ts +179 -0
- package/src/cli/report-tables.ts +136 -18
- package/src/cli/result.ts +12 -4
- package/src/cli/series-search.ts +2 -1
- package/src/cli/symbol-list.ts +47 -11
- package/src/cli/types.ts +4 -0
- package/src/components/chart/composite/composite-chart.tsx +25 -7
- package/src/components/chart/composite/drawing-store.ts +26 -6
- package/src/components/chart/composite/format.ts +13 -1
- package/src/components/chart/composite/interactions.ts +2 -1
- package/src/components/chart/composite/level-labels.ts +30 -0
- package/src/components/chart/composite/levels.ts +17 -6
- package/src/components/chart/composite/panel-surface.tsx +69 -8
- package/src/components/chart/composite/types.ts +6 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +1 -1
- package/src/components/command-bar/routes/root/command-items.ts +32 -6
- package/src/components/command-bar/routes/ticker-search/actions.ts +6 -0
- package/src/components/data-table/view.tsx +23 -3
- package/src/components/index.ts +3 -0
- package/src/components/layout/detached-pane-shell.tsx +1 -0
- package/src/components/layout/floating-pane.tsx +1 -0
- package/src/components/layout/header.tsx +228 -55
- package/src/components/layout/pane/content.tsx +16 -14
- package/src/components/layout/pane/footer/index.tsx +22 -3
- package/src/components/layout/pane/footer/model.ts +99 -4
- package/src/components/layout/pane/header-tabs.tsx +15 -1
- package/src/components/layout/pane/header.tsx +10 -3
- package/src/components/layout/pane/index.tsx +1 -0
- package/src/components/layout/pane/pane-tabs.tsx +9 -1
- package/src/components/onboarding/onboarding-frame.tsx +9 -11
- package/src/components/onboarding/use-onboarding-broker-form.ts +5 -2
- package/src/components/onboarding/wizard-model.ts +10 -3
- package/src/components/ui/button.tsx +11 -4
- package/src/components/ui/choice-dialog.tsx +8 -5
- package/src/components/ui/display.tsx +11 -6
- package/src/components/ui/fields.tsx +100 -20
- package/src/components/ui/icon.tsx +6 -1
- package/src/components/ui/list-row-lines.tsx +87 -0
- package/src/components/ui/list-view.tsx +14 -0
- package/src/components/ui/logo-mark.tsx +64 -0
- package/src/components/ui/number-step.ts +54 -0
- package/src/components/ui/select-button.tsx +5 -4
- package/src/components/ui/select-field.tsx +3 -3
- package/src/components/ui/stat-grid.tsx +28 -3
- package/src/components/ui/status.tsx +20 -4
- package/src/components/ui/tabs.tsx +9 -1
- package/src/components/ui/toggle.tsx +17 -3
- package/src/core/app-services.ts +4 -0
- package/src/core/state/app/instrument.ts +8 -3
- package/src/data/config/store/normalize.ts +4 -1
- package/src/data/plugin-cache.ts +32 -6
- package/src/docs/snapshot.json +5 -5
- package/src/i18n/es.ts +31 -3
- package/src/i18n/ja.ts +31 -3
- package/src/i18n/ko.ts +31 -3
- package/src/i18n/zh-cn.ts +32 -4
- package/src/i18n/zh-tw.ts +32 -4
- package/src/market-data/commodity-names.ts +80 -0
- package/src/market-data/coordinator/auxiliary.ts +3 -1
- package/src/market-data/coordinator/chart.ts +3 -1
- package/src/market-data/futures-board.ts +38 -1
- package/src/market-data/futures-contract.ts +91 -0
- package/src/market-data/fx-closes.ts +78 -1
- package/src/market-data/market/change-basis.ts +219 -0
- package/src/market-data/market/format.ts +28 -12
- package/src/market-data/market/freshness.ts +38 -0
- package/src/market-data/market/status.ts +55 -9
- package/src/market-data/market/year-to-date.ts +46 -0
- package/src/market-data/quotes/contributions.ts +12 -0
- package/src/market-data/quotes/delisting.ts +34 -0
- package/src/market-data/quotes/live-valuation.ts +23 -0
- package/src/market-data/quotes/resolution.ts +8 -2
- package/src/market-data/tax-equivalent.ts +10 -2
- package/src/notifications/app-notifier.ts +2 -2
- package/src/notifications/notification-log.ts +8 -6
- package/src/plugins/builtin/alerts/alert-engine.ts +3 -1
- package/src/plugins/builtin/alerts/cli.ts +26 -18
- package/src/plugins/builtin/alerts/events.ts +1 -0
- package/src/plugins/builtin/alerts/headless.ts +1 -1
- package/src/plugins/builtin/alerts/index.tsx +13 -4
- package/src/plugins/builtin/alerts/research-rules.ts +1 -0
- package/src/plugins/builtin/analytics/risk-pane.tsx +10 -7
- package/src/plugins/builtin/attention/pane.tsx +16 -14
- package/src/plugins/builtin/attention/trending.tsx +8 -6
- package/src/plugins/builtin/awards/pane.tsx +6 -6
- package/src/plugins/builtin/backtest/client.ts +5 -2
- package/src/plugins/builtin/backtest/export.ts +1 -1
- package/src/plugins/builtin/backtest/window.ts +16 -3
- package/src/plugins/builtin/broker-manager/add-flow.tsx +40 -8
- package/src/plugins/builtin/broker-manager/detail.tsx +26 -1
- package/src/plugins/builtin/broker-manager/index.tsx +20 -9
- package/src/plugins/builtin/broker-manager/model.ts +5 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -1
- package/src/plugins/builtin/broker-manager/table.ts +5 -1
- package/src/plugins/builtin/broker-trading/account-picker.tsx +91 -0
- package/src/plugins/builtin/broker-trading/chart-levels.ts +54 -0
- package/src/plugins/builtin/broker-trading/command.ts +103 -0
- package/src/plugins/builtin/broker-trading/controller.ts +688 -0
- package/src/plugins/builtin/broker-trading/dock.tsx +184 -0
- package/src/plugins/builtin/broker-trading/headless.ts +76 -0
- package/src/plugins/builtin/broker-trading/index.tsx +77 -0
- package/src/plugins/builtin/broker-trading/order-feed.ts +383 -0
- package/src/plugins/builtin/broker-trading/orders-data.ts +133 -0
- package/src/plugins/builtin/broker-trading/orders.tsx +437 -0
- package/src/plugins/builtin/broker-trading/overview-orders.tsx +121 -0
- package/src/plugins/builtin/broker-trading/pane-model.ts +207 -0
- package/src/plugins/builtin/broker-trading/pane.tsx +507 -0
- package/src/plugins/builtin/broker-trading/strategy.ts +153 -0
- package/src/plugins/builtin/broker-trading/ticket-parts.tsx +117 -0
- package/src/plugins/builtin/broker-trading/ticket.tsx +578 -0
- package/src/plugins/builtin/buildout/data-runtime.ts +1 -1
- package/src/plugins/builtin/buildout/format.ts +1 -0
- package/src/plugins/builtin/buildout/model/index.ts +16 -7
- package/src/plugins/builtin/buildout/pane/index.tsx +11 -7
- package/src/plugins/builtin/buildout/pane/status.tsx +3 -3
- package/src/plugins/builtin/catalysts/client.ts +2 -2
- package/src/plugins/builtin/catalysts/pane.tsx +3 -3
- package/src/plugins/builtin/chart-composer/cli-options.ts +19 -0
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +2 -1
- package/src/plugins/builtin/chart-composer/headless-schema.ts +3 -3
- package/src/plugins/builtin/chart-composer/headless.ts +2 -1
- package/src/plugins/builtin/chart-composer/option-range.ts +39 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +32 -11
- package/src/plugins/builtin/chart-composer/presets.ts +2 -2
- package/src/plugins/builtin/chart-composer/series-catalog.ts +4 -2
- package/src/plugins/builtin/chart-composer/shortcuts.ts +3 -3
- package/src/plugins/builtin/chart-composer/viewport-labels.ts +5 -2
- package/src/plugins/builtin/chat/index.tsx +1 -1
- package/src/plugins/builtin/chat/status-widget.tsx +1 -1
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +6 -1
- package/src/plugins/builtin/chat/unread-inbox.ts +1 -1
- package/src/plugins/builtin/commodity-balances/client.ts +6 -4
- package/src/plugins/builtin/commodity-balances/headless.ts +41 -7
- package/src/plugins/builtin/commodity-balances/index.tsx +19 -4
- package/src/plugins/builtin/commodity-balances/model.ts +22 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +39 -9
- package/src/plugins/builtin/company-attention/app-rank.tsx +4 -5
- package/src/plugins/builtin/company-attention/pane.tsx +13 -11
- package/src/plugins/builtin/company-kpis/client.ts +3 -2
- package/src/plugins/builtin/company-kpis/headless.ts +5 -7
- package/src/plugins/builtin/company-kpis/model.ts +85 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +30 -15
- package/src/plugins/builtin/composite-plugins.ts +3 -2
- package/src/plugins/builtin/correlation/headless.ts +2 -1
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -0
- package/src/plugins/builtin/correlation/settings.ts +1 -0
- package/src/plugins/builtin/cot/headless.ts +1 -1
- package/src/plugins/builtin/cot/index.tsx +1 -1
- package/src/plugins/builtin/cot/model.ts +35 -12
- package/src/plugins/builtin/cot/pane.tsx +4 -3
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +2 -1
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +2 -1
- package/src/plugins/builtin/credit-conditions/index.tsx +2 -1
- package/src/plugins/builtin/credit-documents/pane.tsx +8 -7
- package/src/plugins/builtin/crypto-board/client.ts +33 -2
- package/src/plugins/builtin/crypto-board/headless.ts +5 -2
- package/src/plugins/builtin/crypto-board/model.ts +28 -8
- package/src/plugins/builtin/debt-maturities/pane.tsx +4 -3
- package/src/plugins/builtin/dividend-yield/headless.ts +30 -8
- package/src/plugins/builtin/dividend-yield/provider-client.ts +3 -1
- package/src/plugins/builtin/doe/pane.tsx +1 -1
- package/src/plugins/builtin/earnings-calls/headless.ts +4 -4
- package/src/plugins/builtin/earnings-calls/lock-note.ts +12 -3
- package/src/plugins/builtin/econ/calendar-model.ts +35 -0
- package/src/plugins/builtin/econ/index.tsx +31 -4
- package/src/plugins/builtin/econ/print-watch.ts +279 -0
- package/src/plugins/builtin/equity-screener/headless.ts +30 -5
- package/src/plugins/builtin/equity-screener/model.ts +68 -2
- package/src/plugins/builtin/equity-screener/pane.tsx +129 -119
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -2
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +29 -7
- package/src/plugins/builtin/exposure/client.ts +4 -1
- package/src/plugins/builtin/exposure/editor.tsx +3 -3
- package/src/plugins/builtin/exposure/evidence.ts +4 -1
- package/src/plugins/builtin/exposure/holdings.ts +3 -1
- package/src/plugins/builtin/exposure/pane.tsx +43 -21
- package/src/plugins/builtin/filing-events/index.tsx +9 -3
- package/src/plugins/builtin/futures/table.tsx +6 -3
- package/src/plugins/builtin/futures-curve/pane.tsx +2 -2
- package/src/plugins/builtin/gpu/board.tsx +4 -1
- package/src/plugins/builtin/gpu/changes.tsx +10 -10
- package/src/plugins/builtin/gpu/equities.tsx +4 -1
- package/src/plugins/builtin/gpu/history.tsx +4 -2
- package/src/plugins/builtin/gpu/pane.tsx +5 -3
- package/src/plugins/builtin/holders/client.ts +2 -1
- package/src/plugins/builtin/holders/headless.ts +2 -1
- package/src/plugins/builtin/holders/thirteenf-match.ts +3 -1
- package/src/plugins/builtin/insider/base-values.ts +76 -0
- package/src/plugins/builtin/insider/client.ts +3 -0
- package/src/plugins/builtin/insider/headless.ts +48 -10
- package/src/plugins/builtin/insider/index.tsx +17 -8
- package/src/plugins/builtin/insider/issuer.ts +34 -4
- package/src/plugins/builtin/insider/signals-client.ts +2 -2
- package/src/plugins/builtin/insider/table-model.ts +35 -13
- package/src/plugins/builtin/insider/table.tsx +5 -2
- package/src/plugins/builtin/iv-history/events.ts +145 -0
- package/src/plugins/builtin/iv-history/format.ts +3 -0
- package/src/plugins/builtin/iv-history/headless.ts +91 -7
- package/src/plugins/builtin/jobs/headless.ts +2 -2
- package/src/plugins/builtin/jobs/lock-note.ts +14 -3
- package/src/plugins/builtin/jodi/pane.tsx +4 -4
- package/src/plugins/builtin/market-halts/model.ts +31 -6
- package/src/plugins/builtin/market-halts/pane.tsx +3 -0
- package/src/plugins/builtin/market-movers/client.ts +4 -3
- package/src/plugins/builtin/market-movers/screener.ts +4 -3
- package/src/plugins/builtin/market-valuation/pane.tsx +2 -1
- package/src/plugins/builtin/members/pane.tsx +8 -3
- package/src/plugins/builtin/news/wire/feed-config.ts +29 -12
- package/src/plugins/builtin/news/wire/index.tsx +7 -2
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +11 -3
- package/src/plugins/builtin/news/wire/rss/cli.ts +3 -2
- package/src/plugins/builtin/news/wire/rss/source.ts +13 -4
- package/src/plugins/builtin/notes/cli.ts +1 -1
- package/src/plugins/builtin/notes/export.ts +17 -6
- package/src/plugins/builtin/notes/files.ts +16 -5
- package/src/plugins/builtin/options/enrichment-model.ts +10 -9
- package/src/plugins/builtin/options/footer.ts +25 -20
- package/src/plugins/builtin/options/live-quotes.ts +33 -18
- package/src/plugins/builtin/options/model-spot.ts +70 -4
- package/src/plugins/builtin/options/view.tsx +118 -35
- package/src/plugins/builtin/options-calculator/pane.tsx +7 -4
- package/src/plugins/builtin/options-positioning/headless.ts +11 -3
- package/src/plugins/builtin/options-positioning/model.ts +24 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +10 -12
- package/src/plugins/builtin/options-scenario/client.ts +19 -1
- package/src/plugins/builtin/options-scenario/headless.ts +13 -6
- package/src/plugins/builtin/options-scenario/pane.tsx +54 -11
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +5 -4
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +3 -0
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +8 -5
- package/src/plugins/builtin/portfolio-list/cli/render.ts +34 -10
- package/src/plugins/builtin/portfolio-list/headless.ts +1 -1
- package/src/plugins/builtin/portfolio-list/pane/data.ts +23 -1
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +33 -14
- package/src/plugins/builtin/portfolio-list/settings.ts +20 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +12 -0
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +24 -3
- package/src/plugins/builtin/power/client.ts +2 -2
- package/src/plugins/builtin/power/pane.tsx +36 -31
- package/src/plugins/builtin/primary-dealers/client.ts +137 -62
- package/src/plugins/builtin/primary-dealers/headless.ts +30 -5
- package/src/plugins/builtin/primary-dealers/index.tsx +3 -2
- package/src/plugins/builtin/primary-dealers/model.ts +179 -129
- package/src/plugins/builtin/primary-dealers/pane.tsx +135 -15
- package/src/plugins/builtin/research/analyst-model.ts +5 -1
- package/src/plugins/builtin/reverse-dcf/client.ts +2 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +4 -3
- package/src/plugins/builtin/risk-factors/index.tsx +12 -3
- package/src/plugins/builtin/scanner/feed.ts +6 -1
- package/src/plugins/builtin/scanner/headless.ts +1 -1
- package/src/plugins/builtin/scanner/lock-note.ts +3 -2
- package/src/plugins/builtin/seasonality/client.ts +2 -1
- package/src/plugins/builtin/sectors/client.ts +4 -3
- package/src/plugins/builtin/series-inventory.ts +1 -0
- package/src/plugins/builtin/shared/cloud-denied.ts +7 -6
- package/src/plugins/builtin/shared/cloud-resource.ts +15 -2
- package/src/plugins/builtin/shared/cloud-upgrade.ts +10 -11
- package/src/plugins/builtin/shared/free-routes.ts +24 -0
- package/src/plugins/builtin/shared/headless-options.ts +11 -0
- package/src/plugins/builtin/shared/pro-lock-note.ts +89 -7
- package/src/plugins/builtin/shared/research-trading.tsx +64 -0
- package/src/plugins/builtin/shared/series-list-detail.tsx +3 -1
- package/src/plugins/builtin/shared/volatility/options.ts +2 -1
- package/src/plugins/builtin/social-mentions/client.ts +2 -1
- package/src/plugins/builtin/social-mentions/headless.ts +1 -1
- package/src/plugins/builtin/social-mentions/lock-note.ts +1 -1
- package/src/plugins/builtin/themes/headless.ts +8 -2
- package/src/plugins/builtin/themes/model.ts +43 -10
- package/src/plugins/builtin/themes/pane.tsx +8 -6
- package/src/plugins/builtin/ticker-detail/overview/model.ts +44 -10
- package/src/plugins/builtin/ticker-detail/overview/option-contract.ts +64 -0
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +82 -21
- package/src/plugins/builtin/ticker-detail/pane.tsx +21 -14
- package/src/plugins/builtin/ticker-detail/quote-footer.ts +5 -1
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +37 -8
- package/src/plugins/builtin/time-sales/pane.tsx +2 -2
- package/src/plugins/builtin/trace-bonds/client.ts +14 -3
- package/src/plugins/builtin/trace-bonds/headless.ts +1 -1
- package/src/plugins/builtin/vol-surface/client.ts +23 -3
- package/src/plugins/builtin/vol-surface/headless.ts +33 -14
- package/src/plugins/builtin/vol-surface/model.ts +30 -10
- package/src/plugins/builtin/vol-surface/pane.tsx +35 -15
- package/src/plugins/builtin/vol-surface/stored.ts +34 -3
- package/src/plugins/builtin/vol-surface/tables.ts +14 -0
- package/src/plugins/builtin-editorial.ts +1 -1
- package/src/plugins/compat.ts +3 -0
- package/src/plugins/external-runtime.ts +5 -0
- package/src/plugins/loader.ts +6 -0
- package/src/plugins/plugin-icon.ts +61 -0
- package/src/plugins/registry/host-actions.ts +2 -1
- package/src/plugins/registry/index.ts +9 -1
- package/src/plugins/runtime/context.tsx +5 -0
- package/src/plugins/runtime/index.tsx +3 -0
- package/src/portfolio/column-values.ts +13 -4
- package/src/portfolio/cost-fx.ts +5 -28
- package/src/public/__snapshots__/public-api.test.ts.snap +5 -0
- package/src/public/broker.ts +8 -0
- package/src/public/market-data.ts +5 -0
- package/src/renderers/dom/desktop/control-styles.ts +7 -1
- package/src/renderers/dom/desktop/controls.tsx +40 -8
- package/src/renderers/dom/desktop/icons.tsx +14 -0
- package/src/renderers/dom/desktop/list-view.tsx +51 -19
- package/src/renderers/dom/desktop/menu.tsx +10 -1
- package/src/renderers/dom/desktop/query-bar.tsx +2 -0
- package/src/renderers/dom/desktop/select-field.tsx +8 -6
- package/src/renderers/dom/host/style.ts +6 -1
- package/src/renderers/dom/host/tabs.tsx +22 -5
- package/src/renderers/dom/host/top-surface.ts +127 -0
- package/src/renderers/dom/styles.css +51 -5
- package/src/renderers/electrobun/bun/core-capabilities.ts +21 -1
- package/src/renderers/electrobun/bun/desktop/backend.ts +10 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +210 -30
- package/src/renderers/electrobun/bun/external-plugins.ts +3 -0
- package/src/renderers/electrobun/shared/protocol.ts +2 -0
- package/src/renderers/electrobun/view/broker-remote-client.ts +16 -0
- package/src/renderers/electrobun/view/external-plugins.ts +1 -0
- package/src/renderers/electrobun/view/news-source.ts +4 -2
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +8 -1
- package/src/renderers/opentui/start.tsx +7 -0
- package/src/series/validate.ts +2 -2
- package/src/sources/gloomberb-cloud/index.ts +57 -17
- package/src/sources/gloomberb-cloud/normalizers.ts +4 -0
- package/src/sources/history-result.ts +3 -0
- package/src/sources/provider-errors.ts +3 -1
- package/src/sources/provider-router/history.ts +49 -6
- package/src/sources/provider-router/index.ts +18 -1
- package/src/state/app/activity.ts +13 -0
- package/src/sync/controller.ts +4 -0
- package/src/sync/core-contributors.ts +62 -11
- package/src/sync/local-only.ts +121 -0
- package/src/sync/react.ts +6 -0
- package/src/sync/types.ts +3 -0
- package/src/telemetry/crash-reports.ts +4 -0
- package/src/telemetry/update-failures-node.ts +59 -0
- package/src/telemetry/update-failures.ts +307 -0
- package/src/tickers/company-name-listing.ts +9 -7
- package/src/tickers/company-name.ts +43 -0
- package/src/tickers/listing-fate.ts +57 -8
- package/src/tickers/search/index.ts +24 -3
- package/src/time-series/price-comparison.ts +35 -0
- package/src/time-series/resolve.ts +52 -11
- package/src/time-series/spec.ts +1 -1
- package/src/time-series/types.ts +5 -0
- package/src/types/broker.ts +56 -1
- package/src/types/config.ts +6 -0
- package/src/types/data-provider.ts +11 -1
- package/src/types/financials.ts +23 -0
- package/src/types/headless.ts +19 -2
- package/src/types/instrument.ts +4 -0
- package/src/types/issuer-listings.ts +28 -0
- package/src/types/plugin.ts +24 -6
- package/src/types/price-history.ts +6 -1
- package/src/types/trading.ts +67 -0
- package/src/ui/host.tsx +4 -0
- package/src/updater/failure.ts +163 -0
- package/src/updater/index.ts +87 -23
- package/src/utils/base-currency.ts +108 -0
- package/src/utils/currency-names.ts +128 -0
- package/src/utils/currency-pair.ts +28 -1
- package/src/utils/currency-units.ts +32 -1
- package/src/utils/dom-screenshot.ts +22 -9
- package/src/utils/exchange-notation.generated.ts +360 -0
- package/src/utils/exchanges.ts +15 -322
- package/src/utils/format.ts +31 -1
- package/src/utils/instrument-identity.ts +38 -1
- package/src/utils/options.ts +46 -1
- package/src/utils/price-history.ts +4 -0
- package/src/utils/reported-money.ts +8 -4
- package/src/utils/sec.ts +68 -0
package/package.json
CHANGED
|
@@ -74,7 +74,7 @@ index cdaa2bca0fabe577cb667056aa6f8f84211189c2..3839e5232742c2467180c344f51a30f1
|
|
|
74
74
|
|
|
75
75
|
// Encrypt function
|
|
76
76
|
diff --git a/dist/api/bun/core/Updater.ts b/dist/api/bun/core/Updater.ts
|
|
77
|
-
index 39daf6d341780af8e30c2c50327162863f5977ec..
|
|
77
|
+
index 39daf6d341780af8e30c2c50327162863f5977ec..0174d2ce1a9a4fa8ae0fd97367293fc5a794286a 100644
|
|
78
78
|
--- a/dist/api/bun/core/Updater.ts
|
|
79
79
|
+++ b/dist/api/bun/core/Updater.ts
|
|
80
80
|
@@ -132,6 +132,19 @@ let updateInfo: {
|
|
@@ -97,7 +97,62 @@ index 39daf6d341780af8e30c2c50327162863f5977ec..bf4a4b615f84904759d4bcd57be0d899
|
|
|
97
97
|
function cleanupExtractionFolder(
|
|
98
98
|
extractionFolder: string,
|
|
99
99
|
keepTarHash: string,
|
|
100
|
-
@@ -
|
|
100
|
+
@@ -158,6 +171,54 @@ function cleanupExtractionFolder(
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
+/**
|
|
105
|
+
+ * Where the running app goes while the new one moves in: `<app>.previous`, or,
|
|
106
|
+
+ * when an older one is still there and cannot be removed (a bundle another
|
|
107
|
+
+ * user owns), a name of its own, so a copy left behind once never blocks
|
|
108
|
+
+ * every later update. The app removes the copies it left at its next start.
|
|
109
|
+
+ */
|
|
110
|
+
+function updateAsidePath(appPath: string): string {
|
|
111
|
+
+ const previous = `${appPath}.previous`;
|
|
112
|
+
+ if (!statSync(previous, { throwIfNoEntry: false })) return previous;
|
|
113
|
+
+ try {
|
|
114
|
+
+ rmSync(previous, { recursive: true, force: true });
|
|
115
|
+
+ } catch (e) {
|
|
116
|
+
+ // Left for the next start to remove; this update takes another name.
|
|
117
|
+
+ }
|
|
118
|
+
+ if (!statSync(previous, { throwIfNoEntry: false })) return previous;
|
|
119
|
+
+ for (let attempt = 0; ; attempt += 1) {
|
|
120
|
+
+ const unique = `${previous}-${Date.now().toString(36)}${attempt ? `-${attempt}` : ""}`;
|
|
121
|
+
+ if (!statSync(unique, { throwIfNoEntry: false })) return unique;
|
|
122
|
+
+ }
|
|
123
|
+
+}
|
|
124
|
+
+
|
|
125
|
+
+/**
|
|
126
|
+
+ * Puts the new app where the running one is. The running app is moved aside
|
|
127
|
+
+ * rather than deleted first, so a move that fails (another volume, a
|
|
128
|
+
+ * read-only one, no permission) puts it back instead of leaving no app at all.
|
|
129
|
+
+ * The copy moved aside is removed when it can be; one that cannot goes at the
|
|
130
|
+
+ * app's next start.
|
|
131
|
+
+ */
|
|
132
|
+
+function replaceAppBundle(runningAppPath: string, newAppPath: string) {
|
|
133
|
+
+ const hadRunningApp = !!statSync(runningAppPath, { throwIfNoEntry: false });
|
|
134
|
+
+ const asidePath = hadRunningApp ? updateAsidePath(runningAppPath) : null;
|
|
135
|
+
+ if (asidePath) renameSync(runningAppPath, asidePath);
|
|
136
|
+
+
|
|
137
|
+
+ emitStatus("replacing-app", "Installing new version...");
|
|
138
|
+
+ try {
|
|
139
|
+
+ renameSync(newAppPath, runningAppPath);
|
|
140
|
+
+ } catch (error) {
|
|
141
|
+
+ if (asidePath) renameSync(asidePath, runningAppPath);
|
|
142
|
+
+ throw error;
|
|
143
|
+
+ }
|
|
144
|
+
+ if (!asidePath) return;
|
|
145
|
+
+ try {
|
|
146
|
+
+ rmSync(asidePath, { recursive: true, force: true });
|
|
147
|
+
+ } catch (e) {
|
|
148
|
+
+ // The new app is in place; the app removes the old copy at its next start.
|
|
149
|
+
+ }
|
|
150
|
+
+}
|
|
151
|
+
+
|
|
152
|
+
const Updater = {
|
|
153
|
+
updateInfo: () => {
|
|
154
|
+
return updateInfo;
|
|
155
|
+
@@ -176,6 +237,12 @@ const Updater = {
|
|
101
156
|
onStatusChangeCallback = callback;
|
|
102
157
|
},
|
|
103
158
|
|
|
@@ -110,7 +165,7 @@ index 39daf6d341780af8e30c2c50327162863f5977ec..bf4a4b615f84904759d4bcd57be0d899
|
|
|
110
165
|
// todo: allow switching channels, by default will check the current channel
|
|
111
166
|
checkForUpdate: async () => {
|
|
112
167
|
emitStatus("checking", "Checking for updates...");
|
|
113
|
-
@@ -196,11 +
|
|
168
|
+
@@ -196,11 +263,11 @@ const Updater = {
|
|
114
169
|
|
|
115
170
|
const cacheBuster = Math.random().toString(36).substring(7);
|
|
116
171
|
const platformPrefix = getPlatformPrefix(
|
|
@@ -124,7 +179,7 @@ index 39daf6d341780af8e30c2c50327162863f5977ec..bf4a4b615f84904759d4bcd57be0d899
|
|
|
124
179
|
|
|
125
180
|
try {
|
|
126
181
|
const updateInfoResponse = await fetch(updateInfoUrl);
|
|
127
|
-
@@ -329,11 +
|
|
182
|
+
@@ -329,11 +396,11 @@ const Updater = {
|
|
128
183
|
|
|
129
184
|
// check if there's a patch file for it
|
|
130
185
|
const platformPrefix = getPlatformPrefix(
|
|
@@ -138,7 +193,7 @@ index 39daf6d341780af8e30c2c50327162863f5977ec..bf4a4b615f84904759d4bcd57be0d899
|
|
|
138
193
|
emitStatus(
|
|
139
194
|
"fetching-patch",
|
|
140
195
|
`Checking for patch: ${currentHash.slice(0, 8)}`,
|
|
141
|
-
@@ -612,12 +
|
|
196
|
+
@@ -612,12 +679,12 @@ const Updater = {
|
|
142
197
|
|
|
143
198
|
const cacheBuster = Math.random().toString(36).substring(7);
|
|
144
199
|
const platformPrefix = getPlatformPrefix(
|
|
@@ -153,6 +208,52 @@ index 39daf6d341780af8e30c2c50327162863f5977ec..bf4a4b615f84904759d4bcd57be0d899
|
|
|
153
208
|
const prevVersionCompressedTarballPath = join(
|
|
154
209
|
appDataFolder,
|
|
155
210
|
"self-extraction",
|
|
211
|
+
@@ -760,7 +827,12 @@ const Updater = {
|
|
212
|
+
mkdirSync(extractionFolder, { recursive: true });
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
- let latestHash = (await Updater.checkForUpdate()).hash;
|
|
216
|
+
+ // Install the build that was downloaded. Checking again here fetched
|
|
217
|
+
+ // the newest manifest instead: once a newer release was out (or the
|
|
218
|
+
+ // check failed offline) its tar was not there and the install
|
|
219
|
+
+ // returned without a word, so a download waiting for a restart could
|
|
220
|
+
+ // never be installed.
|
|
221
|
+
+ let latestHash = updateInfo.hash;
|
|
222
|
+
const latestTarPath = join(extractionFolder, `${latestHash}.tar`);
|
|
223
|
+
|
|
224
|
+
let appBundleSubpath: string = "";
|
|
225
|
+
@@ -894,14 +966,7 @@ const Updater = {
|
|
226
|
+
emitStatus("replacing-app", "Removing old version...");
|
|
227
|
+
|
|
228
|
+
if (currentOS === "macos") {
|
|
229
|
+
- // Remove existing app before installing the new one
|
|
230
|
+
- if (statSync(runningAppBundlePath, { throwIfNoEntry: false })) {
|
|
231
|
+
- rmSync(runningAppBundlePath, { recursive: true });
|
|
232
|
+
- }
|
|
233
|
+
-
|
|
234
|
+
- emitStatus("replacing-app", "Installing new version...");
|
|
235
|
+
- // Move new app to running location
|
|
236
|
+
- renameSync(newAppBundlePath, runningAppBundlePath);
|
|
237
|
+
+ replaceAppBundle(runningAppBundlePath, newAppBundlePath);
|
|
238
|
+
|
|
239
|
+
// Remove quarantine extended attributes to prevent "damaged" error
|
|
240
|
+
// The inner bundle is already signed/notarized, but macOS applies
|
|
241
|
+
@@ -918,14 +983,7 @@ const Updater = {
|
|
242
|
+
// On Linux, we now have directory bundles instead of AppImage files
|
|
243
|
+
// The app is stored in {appDataFolder}/app/
|
|
244
|
+
const appBundleDir = join(appDataFolder, "app");
|
|
245
|
+
-
|
|
246
|
+
- // Remove existing app directory if it exists
|
|
247
|
+
- if (statSync(appBundleDir, { throwIfNoEntry: false })) {
|
|
248
|
+
- rmSync(appBundleDir, { recursive: true });
|
|
249
|
+
- }
|
|
250
|
+
-
|
|
251
|
+
- // Move new app bundle directory to app location
|
|
252
|
+
- renameSync(newAppBundlePath, appBundleDir);
|
|
253
|
+
+ replaceAppBundle(appBundleDir, newAppBundlePath);
|
|
254
|
+
|
|
255
|
+
// Ensure launcher binary is executable
|
|
256
|
+
const launcherPath = join(appBundleDir, "bin", "launcher");
|
|
156
257
|
diff --git a/dist/api/bun/preload/.generated/compiled.ts b/dist/api/bun/preload/.generated/compiled.ts
|
|
157
258
|
index 3ab1d7d8de8938ae60823650fd3a29b952a76cb6..e0e841e6a87ce41533c6bdda8d29400aaf478e31 100644
|
|
158
259
|
--- a/dist/api/bun/preload/.generated/compiled.ts
|
|
@@ -44,6 +44,12 @@ export interface PsdBalanceRow {
|
|
|
44
44
|
unit: string;
|
|
45
45
|
/** Market year, 2026/27. */
|
|
46
46
|
year: string;
|
|
47
|
+
/**
|
|
48
|
+
* YYYY-MM of the crop's newest estimate: the WASDE for grains, oilseeds and
|
|
49
|
+
* cotton, USDA's semiannual report for coffee and sugar. Absent from boards
|
|
50
|
+
* served before it was sent.
|
|
51
|
+
*/
|
|
52
|
+
month?: string | null;
|
|
47
53
|
cropOrder: number;
|
|
48
54
|
countryOrder: number;
|
|
49
55
|
attributeOrder: number;
|
|
@@ -83,6 +83,10 @@ export interface KpiObservation extends Omit<KpiObservationInput, "quote" | "sca
|
|
|
83
83
|
conflict: boolean
|
|
84
84
|
contested?: boolean
|
|
85
85
|
evidence: KpiEvidence[]
|
|
86
|
+
/** Stored facts shown as this one: the same figure under other labels or periods. */
|
|
87
|
+
merged?: string[]
|
|
88
|
+
/** The labels that tell its series apart, the same on each of its facts; the stored ones stay in `dimensions`. */
|
|
89
|
+
seriesLabels?: Record<string, string>
|
|
86
90
|
}
|
|
87
91
|
export interface KpiGuidance extends Omit<KpiGuidanceInput, "quote" | "scale"> {
|
|
88
92
|
id: string
|
|
@@ -97,6 +101,10 @@ export interface KpiGuidance extends Omit<KpiGuidanceInput, "quote" | "scale"> {
|
|
|
97
101
|
direction: GuidanceDirection
|
|
98
102
|
previousId: string | null
|
|
99
103
|
midpointChangePct: number | null
|
|
104
|
+
/** Stored guides shown as this one. */
|
|
105
|
+
merged?: string[]
|
|
106
|
+
/** The labels that tell its series apart, as on its actuals. */
|
|
107
|
+
seriesLabels?: Record<string, string>
|
|
100
108
|
actual: { observationId: string; value: number; outcome: "above" | "below" | "within"; favorable: "beat" | "miss" | "in_line" | "neutral"; difference: number; differencePct: number | null } | null
|
|
101
109
|
}
|
|
102
110
|
interface KpiCoverage {
|
|
@@ -118,6 +126,7 @@ export interface KpiSeries {
|
|
|
118
126
|
currency: string | null
|
|
119
127
|
basis: KpiBasis
|
|
120
128
|
dimensions: Record<string, string>
|
|
129
|
+
seriesLabels?: Record<string, string>
|
|
121
130
|
latest: KpiObservation
|
|
122
131
|
observations: KpiObservation[]
|
|
123
132
|
}
|
|
@@ -38,9 +38,16 @@ export interface CryptoMarketAsset {
|
|
|
38
38
|
/** Market-cap rank within its kind. */
|
|
39
39
|
rank: number;
|
|
40
40
|
price: number;
|
|
41
|
+
/**
|
|
42
|
+
* The day's move as `quote` gives the coin: from the previous UTC day's
|
|
43
|
+
* close, the price at 00:00 UTC. A coin whose close Gloom Cloud cannot date
|
|
44
|
+
* to the last two days moves over 24 hours (`changeBasis` "24h") or not at
|
|
45
|
+
* all ("none"), its previousClose null.
|
|
46
|
+
*/
|
|
41
47
|
previousClose: number | null;
|
|
42
48
|
change: number | null;
|
|
43
49
|
changePercent: number | null;
|
|
50
|
+
changeBasis?: "24h" | "none";
|
|
44
51
|
dayHigh: number | null;
|
|
45
52
|
dayLow: number | null;
|
|
46
53
|
volume24h: number | null;
|
|
@@ -62,6 +69,8 @@ export interface CryptoMarketAsset {
|
|
|
62
69
|
export interface CryptoMarketsPayload {
|
|
63
70
|
version: 1;
|
|
64
71
|
generatedAt: string;
|
|
72
|
+
/** Each asset's change is since 00:00 UTC; a server before it sent the screener's 24-hour move. */
|
|
73
|
+
dayChangeBasis?: "utc-day";
|
|
65
74
|
asOf: string | null;
|
|
66
75
|
status: "available" | "partial" | "unavailable";
|
|
67
76
|
source: {
|
package/src/api-client/data.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
import type { LettersParams } from "./letters";
|
|
28
28
|
import type { IpoCalendarParams, IpoCalendarPayload } from "./ipo";
|
|
29
29
|
import type { TickerChanges } from "../types/ticker-changes";
|
|
30
|
+
import type { IssuerListings } from "../types/issuer-listings";
|
|
30
31
|
import type { OrganizationTickersResponse } from "./organization-tickers";
|
|
31
32
|
import type { CryptoMarketsPayload, StablecoinSupplyHistoryPayload, StablecoinSupplyPayload } from "./crypto-markets";
|
|
32
33
|
import type { CentralBankRatesPayload } from "./central-bank-rates";
|
|
@@ -470,6 +471,20 @@ export class CloudDataApi {
|
|
|
470
471
|
return answers;
|
|
471
472
|
}
|
|
472
473
|
|
|
474
|
+
/** Every listing of the company a listing belongs to (RCI and RCI.B:TSX are Rogers); empty for one the service does not hold. */
|
|
475
|
+
async getCloudIssuerListings(
|
|
476
|
+
symbol: string,
|
|
477
|
+
exchange = "",
|
|
478
|
+
options: { signal?: AbortSignal } = {},
|
|
479
|
+
): Promise<CloudMarketResponse<IssuerListings>> {
|
|
480
|
+
const params = new URLSearchParams({ symbol: symbol.trim().toUpperCase() });
|
|
481
|
+
if (exchange.trim()) params.set("exchange", exchange.trim().toUpperCase());
|
|
482
|
+
return this.request<CloudMarketResponse<IssuerListings>>(
|
|
483
|
+
`/market/issuer-listings?${params}`,
|
|
484
|
+
options.signal ? { signal: options.signal } : undefined,
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
|
|
473
488
|
/** The listed company each organization name resolves to, if any: a trial's lead sponsors, a page at a time. */
|
|
474
489
|
async getCloudOrganizationTickers(names: readonly string[], signal?: AbortSignal): Promise<OrganizationTickersResponse> {
|
|
475
490
|
return this.request<OrganizationTickersResponse>("/market/organization-tickers", {
|
|
@@ -610,12 +625,12 @@ export class CloudDataApi {
|
|
|
610
625
|
}
|
|
611
626
|
|
|
612
627
|
/** `listing` names a listing abroad's venue and company; a US listing needs neither. */
|
|
613
|
-
async getCloudCompanyKpis(symbol: string, options: KpiQueryOptions = {}, listing: IssuerListingParams = {}): Promise<KpisPayload> {
|
|
614
|
-
return this.request<KpisPayload>(companyDisclosurePath("kpis", symbol, options, listing));
|
|
628
|
+
async getCloudCompanyKpis(symbol: string, options: KpiQueryOptions = {}, listing: IssuerListingParams = {}, request?: { signal?: AbortSignal }): Promise<KpisPayload> {
|
|
629
|
+
return this.request<KpisPayload>(companyDisclosurePath("kpis", symbol, options, listing), request);
|
|
615
630
|
}
|
|
616
631
|
|
|
617
|
-
async getCloudCompanyGuidance(symbol: string, options: KpiQueryOptions = {}, listing: IssuerListingParams = {}): Promise<GuidancePayload> {
|
|
618
|
-
return this.request<GuidancePayload>(companyDisclosurePath("guidance", symbol, options, listing));
|
|
632
|
+
async getCloudCompanyGuidance(symbol: string, options: KpiQueryOptions = {}, listing: IssuerListingParams = {}, request?: { signal?: AbortSignal }): Promise<GuidancePayload> {
|
|
633
|
+
return this.request<GuidancePayload>(companyDisclosurePath("guidance", symbol, options, listing), request);
|
|
619
634
|
}
|
|
620
635
|
async getCloudPerpsBoard(query: PerpBoardQuery = {}): Promise<PerpBoardPayload> {
|
|
621
636
|
return this.request(`/cloud/perps/board?${new URLSearchParams(Object.entries(query).filter(([, value]) => value !== undefined).map(([key, value]) => [key, String(value)]))}`);
|
|
@@ -1040,8 +1055,9 @@ export class CloudDataApi {
|
|
|
1040
1055
|
|
|
1041
1056
|
async getCloudSecFilings(
|
|
1042
1057
|
params: CloudSecFilingsParams,
|
|
1058
|
+
options?: { signal?: AbortSignal },
|
|
1043
1059
|
): Promise<CloudSecFilingsResponse> {
|
|
1044
|
-
return this.request<CloudSecFilingsResponse>(cloudSecFilingsPath(params));
|
|
1060
|
+
return this.request<CloudSecFilingsResponse>(cloudSecFilingsPath(params), options);
|
|
1045
1061
|
}
|
|
1046
1062
|
|
|
1047
1063
|
/** Schedule 13D/13G reports about an issuer. Unknown tickers answer 404; no reports is an empty `owners`. */
|
|
@@ -110,6 +110,8 @@ export interface ScreenMetric {
|
|
|
110
110
|
scope: "reported" | "derived" | "observed-subset";
|
|
111
111
|
reason: string | null;
|
|
112
112
|
sourceUrl: string | null;
|
|
113
|
+
/** Set by the client on a Pro field the server left out for a caller without Gloom Pro; never sent. */
|
|
114
|
+
access?: "pro";
|
|
113
115
|
percentile: {
|
|
114
116
|
value: number | null;
|
|
115
117
|
sampleCount: number;
|
package/src/api-client/index.ts
CHANGED
|
@@ -54,6 +54,7 @@ export type {
|
|
|
54
54
|
CrashReportSurface,
|
|
55
55
|
CrashReportsPayload,
|
|
56
56
|
FunctionUsageCount,
|
|
57
|
+
UpdateFailureReport,
|
|
57
58
|
UsageCountsPayload,
|
|
58
59
|
UsageCountsSurface,
|
|
59
60
|
} from "./telemetry";
|
|
@@ -774,6 +775,7 @@ class GloomApiClient {
|
|
|
774
775
|
getCloudTickerChanges = this.data.getCloudTickerChanges.bind(this.data);
|
|
775
776
|
getCloudOrganizationTickers = this.data.getCloudOrganizationTickers.bind(this.data);
|
|
776
777
|
getCloudTickerChangesBatch = this.data.getCloudTickerChangesBatch.bind(this.data);
|
|
778
|
+
getCloudIssuerListings = this.data.getCloudIssuerListings.bind(this.data);
|
|
777
779
|
searchInstrumentsBatch = this.data.searchInstrumentsBatch.bind(this.data);
|
|
778
780
|
getCloudHistory = this.data.getCloudHistory.bind(this.data);
|
|
779
781
|
getCloudExchangeRate = this.data.getCloudExchangeRate.bind(this.data);
|
|
@@ -413,9 +413,10 @@ export class CloudApiRequestTransport {
|
|
|
413
413
|
// change lookup: a note beside a quote, never one of the refused market
|
|
414
414
|
// requests a lookup of many symbols waits out and retries. Nor the
|
|
415
415
|
// tickers beside a list of organization names, which say so in place,
|
|
416
|
-
// or a 13F filer's EDGAR filing list, whose report says it went unchecked
|
|
417
|
-
//
|
|
418
|
-
//
|
|
416
|
+
// or a 13F filer's EDGAR filing list, whose report says it went unchecked,
|
|
417
|
+
// or a company's other listings, beside a list check that still answers
|
|
418
|
+
// for the listing itself. Nor the batched searches and ticker changes a
|
|
419
|
+
// list of symbols starts with: a service without them answers 404, and whatever they leave
|
|
419
420
|
// unanswered is looked up one symbol at a time, which is tracked.
|
|
420
421
|
if (
|
|
421
422
|
path.startsWith("/telemetry/")
|
|
@@ -423,6 +424,7 @@ export class CloudApiRequestTransport {
|
|
|
423
424
|
|| path === "/cloud/geo/layers"
|
|
424
425
|
|| path.startsWith("/cloud/sec/13f/filer?")
|
|
425
426
|
|| path.startsWith("/market/ticker-changes?")
|
|
427
|
+
|| path.startsWith("/market/issuer-listings?")
|
|
426
428
|
|| path === "/market/ticker-changes/batch"
|
|
427
429
|
|| path === "/market/search/batch"
|
|
428
430
|
|| path === "/market/organization-tickers"
|
|
@@ -16,6 +16,23 @@ export interface CrashReportError {
|
|
|
16
16
|
stack?: string;
|
|
17
17
|
plugin?: string;
|
|
18
18
|
pane?: string;
|
|
19
|
+
/** A failed update step, field by field. Servers that do not know it drop it. */
|
|
20
|
+
update?: UpdateFailureReport;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A failed update step as error tracking gets it: fixed values and version
|
|
25
|
+
* numbers only, never a path, URL or the error's own text.
|
|
26
|
+
*/
|
|
27
|
+
export interface UpdateFailureReport {
|
|
28
|
+
phase: "check" | "download" | "verify" | "apply" | "relaunch";
|
|
29
|
+
code: string;
|
|
30
|
+
appVersion: string;
|
|
31
|
+
targetVersion?: string;
|
|
32
|
+
channel: "stable" | "nightly";
|
|
33
|
+
platform: "macos" | "windows" | "linux" | "other";
|
|
34
|
+
arch: "arm64" | "x64" | "other";
|
|
35
|
+
installKind: string;
|
|
19
36
|
}
|
|
20
37
|
|
|
21
38
|
/** Body of `POST /telemetry/errors`. The server forwards each error to error tracking. */
|
package/src/api-client/types.ts
CHANGED
|
@@ -1563,6 +1563,11 @@ export interface CloudMarketResponse<T> {
|
|
|
1563
1563
|
omittedSessions?: unknown;
|
|
1564
1564
|
/** Untrusted until the history adapter validates its boundary dates. */
|
|
1565
1565
|
coverage?: CloudHistoryCoverage;
|
|
1566
|
+
/**
|
|
1567
|
+
* Untrusted: a US listing that no longer trades, `{ status, lastTradeDate,
|
|
1568
|
+
* historyStart }`. Its history ends on `lastTradeDate`. Read by parseListingDelisting.
|
|
1569
|
+
*/
|
|
1570
|
+
delisting?: unknown;
|
|
1566
1571
|
providerMeta?: {
|
|
1567
1572
|
provider?: string;
|
|
1568
1573
|
upstream?: string;
|
|
@@ -8,7 +8,7 @@ import type { AppAction, AppState } from "../state/app/context";
|
|
|
8
8
|
import type { TickerRecord } from "../types/ticker";
|
|
9
9
|
import { findPaneInstance } from "../types/config";
|
|
10
10
|
import type { ReleaseInfo } from "../updater";
|
|
11
|
-
import { canRestartToApply,
|
|
11
|
+
import { canRestartToApply, canRetryUpdate } from "../updater";
|
|
12
12
|
import { getVisiblePaneCycleOrder } from "../components/layout/pane/cycle-order";
|
|
13
13
|
import { requestFunctionHelp, useFunctionHelpHost } from "../plugins/builtin/help/function-card";
|
|
14
14
|
import { buildRegistryHelpIndex, helpFunctionForPane } from "../plugins/builtin/help/function-index";
|
|
@@ -37,21 +37,6 @@ import {
|
|
|
37
37
|
/** Long enough to read a few conflicts and choose Review. */
|
|
38
38
|
const KEYBINDING_NOTICE_DURATION_MS = 15_000;
|
|
39
39
|
|
|
40
|
-
/**
|
|
41
|
-
* Whether the install-update key has something to retry: a release this build
|
|
42
|
-
* can install itself whose last attempt failed. A fresh one downloads on its
|
|
43
|
-
* own, and a manual or managed one names its own command. (A downloaded
|
|
44
|
-
* desktop update has its own use of the key: restarting into it.)
|
|
45
|
-
*/
|
|
46
|
-
export function canRetryUpdate(
|
|
47
|
-
state: Pick<AppState, "updateAvailable" | "updateProgress" | "updateCheckInProgress">,
|
|
48
|
-
): boolean {
|
|
49
|
-
return !!state.updateAvailable
|
|
50
|
-
&& state.updateProgress?.phase === "error"
|
|
51
|
-
&& !state.updateCheckInProgress
|
|
52
|
-
&& canSelfUpdate(state.updateAvailable);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
40
|
/**
|
|
56
41
|
* Tells the user once per launch when `config.json` holds a binding that does
|
|
57
42
|
* not parse, names no action, or lands on a key another action already has.
|
|
@@ -479,9 +479,11 @@ export function bindAppPanePluginRegistry({
|
|
|
479
479
|
throw error;
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
|
+
// Recorded before it registers: what redraws as its contributions land
|
|
483
|
+
// (a broker list and its logo) reads the entry this checkout now is.
|
|
484
|
+
upsertExternalPlugin(entry);
|
|
482
485
|
try {
|
|
483
486
|
await pluginRegistry.register(entry.plugin);
|
|
484
|
-
upsertExternalPlugin(entry);
|
|
485
487
|
} catch (error) {
|
|
486
488
|
upsertExternalPlugin({ ...entry, error: error instanceof Error ? error.message : String(error) });
|
|
487
489
|
reportCrash(error, { kind: "plugin", plugin: pluginId });
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
tickerOpenFailureMessage,
|
|
25
25
|
type TickerOpenTarget,
|
|
26
26
|
} from "../../tickers/open-target";
|
|
27
|
-
import { findExactTickerSearchMatch } from "../../tickers/search";
|
|
27
|
+
import { findExactTickerSearchMatch, upsertTickerFromSearchResult } from "../../tickers/search";
|
|
28
28
|
import { offerTickerListings, publishTickerOpenTarget as publishOpenTarget } from "./ticker-open-target";
|
|
29
29
|
import { parsePublicTickerKey, publicTickerKey } from "../../utils/exchanges";
|
|
30
30
|
import { attentionActionForPane, captureAttentionAction } from "../../telemetry/attention-counts";
|
|
@@ -158,7 +158,7 @@ export function useAppTickerOpenRuntime({
|
|
|
158
158
|
persistLayout(nextLayout);
|
|
159
159
|
}
|
|
160
160
|
if (paneType === TICKER_RESEARCH_PANE_ID && options?.tabId) {
|
|
161
|
-
dispatch({ type: "UPDATE_PANE_STATE", paneId: existing.instanceId, patch: { activeTabId: options.tabId } });
|
|
161
|
+
dispatch({ type: "UPDATE_PANE_STATE", paneId: existing.instanceId, patch: { ...options.tabState, activeTabId: options.tabId } });
|
|
162
162
|
}
|
|
163
163
|
focusVisiblePane(existing.instanceId, nextLayout);
|
|
164
164
|
return;
|
|
@@ -186,7 +186,7 @@ export function useAppTickerOpenRuntime({
|
|
|
186
186
|
);
|
|
187
187
|
persistLayout(nextLayout);
|
|
188
188
|
if (paneType === TICKER_RESEARCH_PANE_ID && options?.tabId) {
|
|
189
|
-
dispatch({ type: "UPDATE_PANE_STATE", paneId: instance.instanceId, patch: { activeTabId: options.tabId } });
|
|
189
|
+
dispatch({ type: "UPDATE_PANE_STATE", paneId: instance.instanceId, patch: { ...options.tabState, activeTabId: options.tabId } });
|
|
190
190
|
}
|
|
191
191
|
activatePane(instance.instanceId);
|
|
192
192
|
}, [
|
|
@@ -205,9 +205,21 @@ export function useAppTickerOpenRuntime({
|
|
|
205
205
|
// Before resolving, so a refused open adds no ticker either.
|
|
206
206
|
if (refuseWhileOwnerOff(rawSymbol, options, () => { void openPinnedTicker(rawSymbol, options); })) return;
|
|
207
207
|
const recordAttention = captureAttentionAction();
|
|
208
|
-
|
|
208
|
+
let selected = options?.instrument !== undefined && (options.instrument || options.listing)
|
|
209
|
+
? { ticker: await tickerRepository.loadTicker(rawSymbol), created: false } : null;
|
|
210
|
+
// A listing the caller chose, such as one contract of an options chain,
|
|
211
|
+
// opens as given: no search could name it better than its own chain.
|
|
212
|
+
if (selected && !selected.ticker && options?.listing) {
|
|
213
|
+
const { listing, instrument } = options;
|
|
214
|
+
selected = await upsertTickerFromSearchResult(tickerRepository, {
|
|
215
|
+
providerId: instrument?.brokerId ?? "", ...(instrument?.brokerInstanceId ? { brokerInstanceId: instrument.brokerInstanceId } : {}),
|
|
216
|
+
symbol: rawSymbol, name: listing.name, exchange: listing.exchange, type: listing.type,
|
|
217
|
+
...(listing.currency ? { currency: listing.currency } : {}), ...(instrument ? { brokerContract: instrument } : {}),
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
const selectedTicker = selected?.ticker;
|
|
209
221
|
const target = selectedTicker
|
|
210
|
-
? { symbol: selectedTicker.metadata.ticker, ticker: selectedTicker, created:
|
|
222
|
+
? { symbol: selectedTicker.metadata.ticker, ticker: selectedTicker, created: selected!.created, instrument: options?.instrument, listing: options?.listing }
|
|
211
223
|
: await resolveOpenTickerTarget(rawSymbol, options?.instrument === null);
|
|
212
224
|
if (!target) return;
|
|
213
225
|
placePinnedTickerTarget(target, options, rawSymbol);
|
|
@@ -105,7 +105,7 @@ export function bindPluginRegistryRuntimeAccess({
|
|
|
105
105
|
pluginRegistry.events.emit("config:changed", { config: nextConfig });
|
|
106
106
|
},
|
|
107
107
|
|
|
108
|
-
createBrokerInstance: async (brokerType, label, values) => {
|
|
108
|
+
createBrokerInstance: async (brokerType, label, values, options = {}) => {
|
|
109
109
|
const instanceId = createBrokerInstanceId(
|
|
110
110
|
brokerType,
|
|
111
111
|
label,
|
|
@@ -118,6 +118,7 @@ export function bindPluginRegistryRuntimeAccess({
|
|
|
118
118
|
connectionMode: typeof values.connectionMode === "string" ? values.connectionMode : undefined,
|
|
119
119
|
config: values,
|
|
120
120
|
enabled: true,
|
|
121
|
+
...(options.localOnly ? { localOnly: true } : {}),
|
|
121
122
|
};
|
|
122
123
|
const nextConfig = {
|
|
123
124
|
...stateRef.current.config,
|
|
@@ -153,12 +154,15 @@ export function bindPluginRegistryRuntimeAccess({
|
|
|
153
154
|
instance.id === instanceId
|
|
154
155
|
? (() => {
|
|
155
156
|
const nextValues = options.replaceConfig ? values : { ...instance.config, ...values };
|
|
157
|
+
const { localOnly: wasLocalOnly, ...rest } = instance;
|
|
158
|
+
const localOnly = options.localOnly ?? wasLocalOnly === true;
|
|
156
159
|
return {
|
|
157
|
-
...
|
|
160
|
+
...rest,
|
|
158
161
|
label: options.label ?? instance.label,
|
|
159
162
|
enabled: options.enabled ?? instance.enabled,
|
|
160
163
|
connectionMode: typeof nextValues.connectionMode === "string" ? nextValues.connectionMode : instance.connectionMode,
|
|
161
164
|
config: nextValues,
|
|
165
|
+
...(localOnly ? { localOnly: true } : {}),
|
|
162
166
|
};
|
|
163
167
|
})()
|
|
164
168
|
: instance,
|
|
@@ -6,6 +6,7 @@ import type { AppAction, AppState } from "../../state/app/context";
|
|
|
6
6
|
import {
|
|
7
7
|
applyUpdate,
|
|
8
8
|
canRestartToApply,
|
|
9
|
+
canRetryUpdate,
|
|
9
10
|
canSelfUpdate,
|
|
10
11
|
checkForUpdateDetailed,
|
|
11
12
|
discardStagedUpdate,
|
|
@@ -15,6 +16,8 @@ import {
|
|
|
15
16
|
type UpdateProgress,
|
|
16
17
|
} from "../../updater";
|
|
17
18
|
import { resolveUpdateChannel, stagedUpdateFitsChannel } from "../../updater/channel";
|
|
19
|
+
import { updateFailureReason } from "../../updater/failure";
|
|
20
|
+
import { t, tf } from "../../i18n";
|
|
18
21
|
import type { UpdateChannel } from "../../types/config";
|
|
19
22
|
import { VERSION } from "../../version";
|
|
20
23
|
import { debugLog } from "../../utils/debug-log";
|
|
@@ -27,11 +30,14 @@ const UPDATE_CHECK_INTERVAL_MS = 60 * 60_000; // hourly
|
|
|
27
30
|
const updateLog = debugLog.createLogger("update");
|
|
28
31
|
|
|
29
32
|
/**
|
|
30
|
-
* The header
|
|
31
|
-
*
|
|
33
|
+
* The header says why an update failed in a few words and the command bar
|
|
34
|
+
* shows the whole error: the log keeps what the updater actually said, with
|
|
35
|
+
* the step and the reason.
|
|
32
36
|
*/
|
|
33
37
|
function logUpdateFailure(progress: UpdateProgress): void {
|
|
34
|
-
if (progress.phase === "error")
|
|
38
|
+
if (progress.phase === "error") {
|
|
39
|
+
updateLog.error("update failed", { error: progress.error, phase: progress.failure?.phase, code: progress.failure?.code });
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
/** An update is being downloaded, applied, or is downloaded and waiting for a restart. */
|
|
@@ -127,7 +133,9 @@ export function useAppUpdateRuntime({
|
|
|
127
133
|
return { kind: "error", error: message || "Update check failed" };
|
|
128
134
|
});
|
|
129
135
|
|
|
130
|
-
if (result.kind === "error")
|
|
136
|
+
if (result.kind === "error") {
|
|
137
|
+
updateLog.warn("update check failed", { error: result.error, code: result.failure?.code });
|
|
138
|
+
}
|
|
131
139
|
|
|
132
140
|
if (!manual) {
|
|
133
141
|
if (result.kind === "available" && result.release.tagName !== declinedTagRef.current) {
|
|
@@ -154,13 +162,25 @@ export function useAppUpdateRuntime({
|
|
|
154
162
|
return;
|
|
155
163
|
}
|
|
156
164
|
|
|
157
|
-
|
|
165
|
+
// The reason in a few words, as the failed banner gives it; the log has the error.
|
|
166
|
+
const reason = result.failure ? t(updateFailureReason(result.failure)) : result.error;
|
|
167
|
+
dispatch({ type: "SET_UPDATE_NOTICE", notice: tf("Update check failed: {reason}", { reason }) });
|
|
158
168
|
}, [dispatch, stateRef]);
|
|
159
169
|
|
|
160
170
|
const runUpdateCommand = useCallback(() => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
171
|
+
const state = stateRef.current;
|
|
172
|
+
if (canRestartToApply(state.updateProgress)) {
|
|
173
|
+
restartToApplyUpdate();
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
// After a failed download or install, the command tries again, as the key does.
|
|
177
|
+
if (canRetryUpdate(state)) {
|
|
178
|
+
startUpdate(state.updateAvailable!);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (state.updateProgress?.phase === "error") dispatch({ type: "SET_UPDATE_PROGRESS", progress: null });
|
|
182
|
+
void runUpdateCheck(true);
|
|
183
|
+
}, [dispatch, restartToApplyUpdate, runUpdateCheck, startUpdate, stateRef]);
|
|
164
184
|
|
|
165
185
|
useEffect(() => {
|
|
166
186
|
if (!enabled || isDetachedWindow) return;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"src/plugins/builtin/account-management/pane.tsx": {
|
|
3
|
+
"hasSession || apiClient.isSignedIn()": "Signed out, every tab is the same sign-in wall."
|
|
4
|
+
},
|
|
5
|
+
"src/plugins/builtin/analytics/index.tsx": {
|
|
6
|
+
"portfolioTabs.length > 0": "The tabs are the user's portfolios; with none there is nothing to choose between."
|
|
7
|
+
},
|
|
8
|
+
"src/plugins/builtin/analytics/risk-pane.tsx": {
|
|
9
|
+
"portfolio": "No local portfolio yet: the pane says to add holdings instead of offering views of nothing."
|
|
10
|
+
},
|
|
11
|
+
"src/plugins/builtin/attention/pane.tsx": {
|
|
12
|
+
"!signInWall": "Signed out, every tab is the same sign-in wall."
|
|
13
|
+
},
|
|
14
|
+
"src/plugins/builtin/awards/pane.tsx": {
|
|
15
|
+
"!denied": "Access denied draws the sign-in or plan wall for every tab."
|
|
16
|
+
},
|
|
17
|
+
"src/plugins/builtin/backtest/pane.tsx": {
|
|
18
|
+
"symbol": "No ticker yet: the pane asks for one before any view applies."
|
|
19
|
+
},
|
|
20
|
+
"src/plugins/builtin/catalysts/pane.tsx": {
|
|
21
|
+
"!openId": "An open event replaces the list by design and registers its own Evidence and History strip."
|
|
22
|
+
},
|
|
23
|
+
"src/plugins/builtin/cloud/team/pane.tsx": {
|
|
24
|
+
"signedIn": "The tabs are the user's teams; signed out there are none and the pane is a sign-in wall."
|
|
25
|
+
},
|
|
26
|
+
"src/plugins/builtin/company-attention/pane.tsx": {
|
|
27
|
+
"!signInWall && !openCompany && !app": "Signed out it is a sign-in wall; an open company or app replaces the board by design and registers its own strip."
|
|
28
|
+
},
|
|
29
|
+
"src/plugins/builtin/company-kpis/pane.tsx": {
|
|
30
|
+
"symbol && !signInWall": "No ticker yet, or signed out: every tab would be the same prompt or sign-in wall."
|
|
31
|
+
},
|
|
32
|
+
"src/plugins/builtin/congress-trades/pane.tsx": {
|
|
33
|
+
"tickerFilter": "A ticker's own congressional trades are one list; the Trades, Members and Tickers tabs belong to the whole-market view."
|
|
34
|
+
},
|
|
35
|
+
"src/plugins/builtin/debt-maturities/pane.tsx": {
|
|
36
|
+
"symbol && !signInWall": "No ticker yet, or signed out: every tab would be the same prompt or sign-in wall."
|
|
37
|
+
},
|
|
38
|
+
"src/plugins/builtin/earnings-ripple/pane.tsx": {
|
|
39
|
+
"holdings.length": "No holdings to ripple from yet: the pane says how to add them instead of offering views of nothing."
|
|
40
|
+
},
|
|
41
|
+
"src/plugins/builtin/estimate-revisions/pane.tsx": {
|
|
42
|
+
"!symbol || signInWall": "No ticker yet, or signed out: every tab would be the same prompt or sign-in wall."
|
|
43
|
+
},
|
|
44
|
+
"src/plugins/builtin/gpu/pane.tsx": {
|
|
45
|
+
"!signIn": "Signed out or unverified, every tab is the same sign-in wall."
|
|
46
|
+
},
|
|
47
|
+
"src/plugins/builtin/portfolio-list/pane/index.tsx": {
|
|
48
|
+
"showCollectionTabs": "The tabs are the pane's collections; a single collection has nothing to switch to."
|
|
49
|
+
},
|
|
50
|
+
"src/plugins/builtin/power/pane.tsx": {
|
|
51
|
+
"!signInWall": "Signed out, every tab is the same sign-in wall."
|
|
52
|
+
},
|
|
53
|
+
"src/plugins/builtin/research-search/pane.tsx": {
|
|
54
|
+
"signInRequired || verificationRequired": "Signed out or unverified, every mode is the same sign-in wall."
|
|
55
|
+
},
|
|
56
|
+
"src/plugins/builtin/shared/filing-year-reader.tsx": {
|
|
57
|
+
"years.length > 1": "The tabs are the filings on record, known once their list answers; a single filing has no other year to pick."
|
|
58
|
+
},
|
|
59
|
+
"src/plugins/builtin/supply-chain/pane.tsx": {
|
|
60
|
+
"symbol": "No ticker yet: the pane asks for one before any view applies."
|
|
61
|
+
},
|
|
62
|
+
"src/plugins/builtin/ticker-detail/pane.tsx": {
|
|
63
|
+
"!paneSettings.hideTabs && ticker": "The hideTabs setting locks the pane to one view, and with no ticker selected there is nothing to research."
|
|
64
|
+
}
|
|
65
|
+
}
|